﻿using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 通用对象池类（支持任何Unity组件类型）
/// </summary>
/// <typeparam name="T">组件类型</typeparam>
public class ObjectPool<T> where T : Component
{
    private Queue<T> pool = new Queue<T>();
    private T prefab;
    private Transform parent;

    /// <summary>
    /// 对象池构造函数
    /// </summary>
    /// <param name="prefab">预制体</param>
    /// <param name="initialSize">初始池大小</param>
    /// <param name="parent">父物体（可选）</param>
    public ObjectPool(T prefab, int initialSize, Transform parent = null)
    {
        this.prefab = prefab;
        this.parent = parent;
        InitializePool(initialSize);
    }

    // 初始化对象池
    private void InitializePool(int initialSize)
    {
        for (int i = 0; i < initialSize; i++)
        {
            CreateNewObject();
        }
    }

    // 创建新对象并加入池中
    private T CreateNewObject()
    {
        T newObj = Object.Instantiate(prefab, parent);
        newObj.gameObject.SetActive(false);
        pool.Enqueue(newObj);
        return newObj;
    }

    /// <summary>
    /// 从池中获取对象
    /// </summary>
    /// <param name="position">生成位置</param>
    /// <param name="rotation">生成旋转</param>
    /// <returns>池中的对象</returns>
    public T Get(Vector3 position, Quaternion rotation)
    {
        if (pool.Count == 0)
        {
            CreateNewObject();
        }

        T obj = pool.Dequeue();
        SetupObject(obj, position, rotation);
        return obj;
    }

    // 设置取出的对象
    private void SetupObject(T obj, Vector3 position, Quaternion rotation)
    {
        obj.transform.SetPositionAndRotation(position, rotation);
        obj.gameObject.SetActive(true);

        // 可选：发送唤醒通知
        IPoolable poolable = obj.GetComponent<IPoolable>();
        poolable?.OnSpawn();
    }

    /// <summary>
    /// 将对象返回到池中
    /// </summary>
    /// <param name="obj">要返回的对象</param>
    public void Return(T obj)
    {
        // 可选：发送回收通知
        IPoolable poolable = obj.GetComponent<IPoolable>();
        poolable?.OnDespawn();

        obj.gameObject.SetActive(false);
        pool.Enqueue(obj);
    }

    /// <summary>
    /// 扩展池大小
    /// </summary>
    /// <param name="amount">扩展数量</param>
    public void Expand(int amount)
    {
        for (int i = 0; i < amount; i++)
        {
            CreateNewObject();
        }
    }

    /// <summary>
    /// 清空对象池
    /// </summary>
    public void Clear()
    {
        while (pool.Count > 0)
        {
            T obj = pool.Dequeue();
            if (obj != null)
            {
                Object.Destroy(obj.gameObject);
            }
        }
    }
}

/// <summary>
/// 可选接口：用于对象回收/取出时的自定义逻辑
/// </summary>
public interface IPoolable
{
    void OnSpawn();   // 从池中取出时调用
    void OnDespawn(); // 放回池中时调用
}
